# coding=utf-8
import tornado
import tornado.web
import tornado.ioloop
from tornado.httpclient import AsyncHTTPClient

import json
import time
import datetime
import pymongo 
import dateutil.parser
import pandas as pd
import numpy as np
import sys
import requests
import threading


import os
import urllib
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import math
#import tushare as ts
import json
import pymongo
#import yaml
import time
import tensorflow as tf
import numpy as np
from threading import Timer
#import superholyshitopfinal as op
#from odo import odo
import pandas as pd
from socket import *
import sys
reload(sys)  
sys.setdefaultencoding('utf-8')








class MLP(object):  

    def __init__(self,code): 

        self.sess = tf.Session(graph=tf.Graph())        
        meta_graph_def = tf.saved_model.loader.load(self.sess, 'serve', code)
        signature = meta_graph_def.signature_def
        signature_key = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
        input_key = 'x'
        output_key = 'y'
        metric_key = 'metric'
        target_key = 'target'
        keep_key = 'keep'

        x_tensor_name = signature[signature_key].inputs[input_key].name
        target_tensor_name = signature[signature_key].inputs[target_key].name
        keep_tensor_name = signature[signature_key].inputs[keep_key].name
        y_tensor_name = signature[signature_key].outputs[output_key].name
        metric_tensor_name = signature[signature_key].outputs[metric_key].name

        self.x = self.sess.graph.get_tensor_by_name(x_tensor_name)
        self.target = self.sess.graph.get_tensor_by_name(target_tensor_name)
        self.keep = self.sess.graph.get_tensor_by_name(keep_tensor_name)
        self.y = self.sess.graph.get_tensor_by_name(y_tensor_name)
        self.metric = self.sess.graph.get_tensor_by_name(metric_tensor_name)

    def predict(self,X):

        #X = np.array(X).reshape(-1,4,5)
        with self.sess.as_default() as sess: 
            Y = sess.run(self.y,feed_dict={self.x:X, self.keep:1.0})
        return Y

def load_model():
    root = os.getcwd()
    model_path = os.path.join(root, 'models')
    model_names = os.listdir(model_path)
    models = dict()
    for m in model_names:
        models[m] = MLP(os.path.join(model_path, m))
    return models


def getDate(begin, before):
    info = list()
    begin = begin.split('-')
    d = datetime.date(int(begin[0]), int(begin[1]), int(begin[2]))
    delta = datetime.timedelta(days=1)
    for _ in range(before):
        d -= delta
        info.append(d.strftime("%Y-%m-%d"))
    return info

class DateData:
    def __init__(self, start, end, table):
        client=pymongo.MongoClient('47.98.203.142',27017)
        db=client.admin
        db = db.authenticate('myUserAdmin','abc123')
        self.db = client.chinastock
        self.HSI_back = self.db[table]
        self.start = dateutil.parser.parse(start)
        self.end = dateutil.parser.parse(end)

    def data(self):
        data = self.HSI_back.find({'date': {'$gte': self.start, '$lte': self.end}})
        data_list = [x for x in data]
        pd_data = pd.DataFrame(data_list)
        return pd_data

def load_data():
    key = ['adj close', 'open', 'high', 'low', 'volume', 'date']
    data = dict()
    info = getDate(nowTime, 50)
    for t in table:
        if t == 'HSI': d = DateData(info[-1], nowTime, t)
        else: d = DateData(info[-1], info[0], t)
        da = d.data()
        da = da[key]
        da = da.values
        data[t] = da
    return data


def normalize_minmax(data,minData,maxData):
    return (data - minData * 0.9) / (maxData - minData * 0.9)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("服务器正在运行")


class View(tornado.web.RequestHandler):
    def get(self):
        self.write(json.dumps(data2))


class ViewHSI(tornado.web.RequestHandler):
    def get(self):
        self.write(json.dumps(HSI))


class StockGet(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def post(self):
        stock = self.get_argument('stock')
        url = 'http://hq.sinajs.cn/list=%s'%(str(stock))
        http = AsyncHTTPClient()
        http.fetch(url, self._on_download)
    
    @tornado.gen.coroutine
    def _on_download(self, response):
        body = response.body.decode('gbk')
        body = body.split(u';')
        result = dict()
        for b in body:
            if len(b) <=5:
                continue
            stock = b.split(u'=')[0].replace(u'var hq_str_rt_', u'')
            stock = stock.replace('\n', '')
            b = b.split(u'=')[-1]
            b = b.split(u',') 
            item = {'open': b[2],
                    'high': b[4],
                    'low': b[5],
                    'now': b[6],
                    'volume': b[12],
                    'stock': stock,
                    'date': b[17],
                    'time': b[18]
                    }
            result[stock] = item
        self.write(json.dumps(result))
        self.finish()

def run():
    while True:
        time.sleep(1)
        global nowTime, data, data2, HSI
        GnowTime = time.strftime('%Y-%m-%d', time.localtime(time.time()))
        if nowTime != GnowTime:
            nowTime = GnowTime
            data = load_data()
        info = list()
        for t in table:
            if t == 'HSI': t = 'rt_hk' + t
            else:
                t = t.replace('.HK', '')
                t = 'rt_hk0' + t
            info.append(t)
        info = ",".join(info)
        stock = {'stock':info}
        response = requests.post('http://127.0.0.1:8888/nowlist', data=stock).json()
        for k, v in response.items():
            if k[2:] == 'HSI': k2 = 'HSI'
            else: k2 = k[3:]+'.HK'
            v2 = np.array([float(v['now']), float(v['open']), float(v['high']), float(v['low']), float(v['volume']), v['date']])
            v3 = data[k2][-19:]
            if k2 == "HSI": v4 = data[k2]
            else: v4 = np.row_stack([v3, v2])
            info = dict()
            for m_k, m_v in models.items():
                lag = m_k.split('lag_')[-1].split('_')[0]
                code = m_k.split('code_')[-1].split("_")[0]
                if code != 'HSI': code = code.replace('HK', '') + '.HK'
                if code != k2: continue
                X = v4[0-int(lag):,:-1]
                date = v4[0-int(lag):,-1:]
                X = X.reshape(-1, X.shape[0], X.shape[1])
                info[m_k] = {'result':str(m_v.predict(X)[0,0]), 'input': str(date)}
            if k2 == "HSI": HSI = info
            else: data2[k] = info
        time.sleep(59)

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
        (r"/view", View),
        (r"/hsi", ViewHSI),
        (r"/nowlist", StockGet),
    ])

if __name__ == "__main__":
    # 启动模型
    models = load_model()
    # 本机现在日期 如果服务器日期不对请手动输入例如：2018-01-01
    nowTime = time.strftime('%Y-%m-%d', time.localtime(time.time()))
    # mongodb表名字
    table = ['HSI', '0700.HK','0005.HK','0883.HK','1928.HK','0066.HK','1997.HK','0144.HK','2382.HK','1113.HK','1093.HK',]
    # 加载需要的股票数据
    data = load_data()
    # 预测后数据的对象
    data2 = dict()
    HSI = dict()
    # 启动预测程序
    t1 = threading.Thread(target=run)
    t1.setDaemon(True)
    t1.start()
    # 以下是启动服务器
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()
